﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using VNet.VisiSuite.Common.Helper;
using VNet.VisiSuite.Controls;
using VNet.VisiSuite.Service.Contact.Message.Security;
using VNet.VisiSuite.Service.Contact.Message.Base;
using VNet.VisiSuite.VisiAdmin.Common;
using VNet.VisiSuite.VisiAdmin.Common.Helpers;
using VNet.VisiSuite.VisiAdmin.Models;
using VNet.VisiSuite.VisiAdmin.Providers;
using VNet.VisiSuite.VisiAdmin.Views;
using VNet.VisiSuite.Service.Contact.Message.Item;
using VNet.VisiSuite.Common.Resource;
using VNet.VisiSuite.Service.Contact.Enum;
using System.Windows;
using VNet.VisiSuite.Common;

namespace VNet.VisiSuite.VisiAdmin.ViewModels
{
    public class PlantViewModel : BaseViewModel
    {
        #region Fields
        private ObservableCollection<PlantModel> _plants;
        private List<PlantModel> _backupPlants;
        private List<CellModel> _backupCells;
        private List<AreaModel> _backupAreas;
        private object _selectedObject;
        private object _pendingObject;
        private PlantModel _cloneSelectedPlant;
        private AreaModel _cloneSelectedArea;
        private CellModel _cloneSelectedCell;
        private string _contentPaneHeader;
        private const string _plantHeader = "Plant Properties";
        private const string _areaHeader = "Area Properties";
        private const string _cellHeader = "Cell Properties";
        private const string _defaultDateFormat = "d-MMM-yyyy h:mm tt";
        private VNetMenuItem _areaMenuIcon;
        private VNetMenuItem _productMenuIcon;
        private VNetMenuItem _addAreaIcon;
        private VNetMenuItem _addCellIcon;
        private VNetMenuItem _statusMenuIcon;
        #endregion

        public PlantViewModel()
        {
            PageTitle = TitleString.PlantViewAdminTitle;

            TopLeftButtonIcons = new ObservableCollection<VNetMenuItem> { new VNetMenuItem(null, "Logout VisiAdmin", CommonConstants.VNetIcon.AppbarDoorLeave, VNetMenuItemType.WhiteBackgroundTheme, OnLogout), };

            TopRightButtonIcons = new ObservableCollection<VNetMenuItem> 
            { 
                new VNetMenuItem("Add Plant", "Add Plant", CommonConstants.VNetIcon.AppbarListAdd, VNetMenuItemType.WhiteBackgroundTheme, OnAddPlant),
                (_addAreaIcon = new VNetMenuItem("Add Area", "Add Area", CommonConstants.VNetIcon.AppbarListAdd, VNetMenuItemType.WhiteBackgroundTheme, OnAddArea){IsEnabled=false}),
                (_addCellIcon = new VNetMenuItem("Add Cell", "Add Cell", CommonConstants.VNetIcon.AppbarListAdd, VNetMenuItemType.WhiteBackgroundTheme, OnAddCell){IsEnabled=false}),            
            };


            BottomMenuItems = new ObservableCollection<VNetMenuItem>();

            _areaMenuIcon = new VNetMenuItem("Edit Area", "Edit Area", CommonConstants.VNetIcon.AppbarEdit, VNetMenuItemType.BlackBackgroundTheme, EditAreaMenuClick);
            if (NavigationManager.LoggedInUser.Permission.HasFlag(UserPermission.EditParts))
            {
                _areaMenuIcon.IsEnabled = false;
                BottomMenuItems.Add(_areaMenuIcon);
            }

            _statusMenuIcon = new VNetMenuItem("Status", "VisiBoard Status", CommonConstants.VNetIcon.AppbarGraphBar, VNetMenuItemType.BlackBackgroundTheme, VisiBoardStatusMenuClick);
            _statusMenuIcon.IsEnabled = false;
            BottomMenuItems.Add(_statusMenuIcon);

            _productMenuIcon = new VNetMenuItem("Products", "Products", CommonConstants.VNetIcon.AppbarBrick, VNetMenuItemType.BlackBackgroundTheme, ProductsMenuClick);
            BottomMenuItems.Add(_productMenuIcon);
            

            if (NavigationManager.LoggedInUser.Permission.HasFlag(UserPermission.EditUsers))
                BottomMenuItems.Add(new VNetMenuItem("Users", "Edit Users", CommonConstants.VNetIcon.AppbarPeople, VNetMenuItemType.BlackBackgroundTheme, UserMenuClick, "20 10 10 10"));

            SavePlantCommand = new RelayCommand(DoSavePlant);
            CancelPlantCommand = new RelayCommand(DoCancelPlant);
            DeletePlantCommand = new RelayCommand(DoDeletePlant);

            SaveAreaCommand = new RelayCommand(DoSaveArea);
            CancelAreaCommand = new RelayCommand(DoCancelArea);
            DeleteAreaCommand = new RelayCommand(DoDeleteArea);

            SaveCellCommand = new RelayCommand(DoSaveCell);
            CancelCellCommand = new RelayCommand(DoCancelCell);
            DeleteCellCommand = new RelayCommand(DoDeleteCell);
        }

        #region Properties

        public RelayCommand SavePlantCommand { get; set; }
        public RelayCommand RestorePlantCommand { get; set; }
        public RelayCommand CancelPlantCommand { get; set; }
        public RelayCommand DeletePlantCommand { get; set; }

        public RelayCommand SaveAreaCommand { get; set; }
        public RelayCommand CancelAreaCommand { get; set; }
        public RelayCommand DeleteAreaCommand { get; set; }
        public RelayCommand RestoreAreaCommand { get; set; }

        public RelayCommand SaveCellCommand { get; set; }
        public RelayCommand CancelCellCommand { get; set; }
        public RelayCommand DeleteCellCommand { get; set; }
        public RelayCommand RestoreCellCommand { get; set; }

        public ObservableCollection<PlantModel> Plants
        {
            get { return _plants; }
            set
            {
                _plants = value;
                OnPropertyChanged("Plants");
            }
        }

        public object SelectedObject
        {
            get { return _selectedObject; }
            set
            {
                if (_selectedObject != null)
                {
                    var currentType = _selectedObject.GetType();
                    if (currentType == typeof(PlantModel) && IsPlantPendingChange(value)
                        || currentType == typeof(AreaModel) && IsAreaPendingChange(value)
                        || currentType == typeof(CellModel) && IsCellPendingChange(value)
                        )
                    {
                        return;
                    }
                }

                _selectedObject = null;
                OnPropertyChanged("SelectedObject");

                ContentPaneHeader = _plantHeader;
                CloneSelectedPlant = null;
                CloneSelectedArea = null;
                CloneSelectedCell = null;
                _areaMenuIcon.IsEnabled = false;
                _statusMenuIcon.IsEnabled = false;
                _addAreaIcon.IsEnabled = false;
                _addCellIcon.IsEnabled = false;

                if (value != null)
                {
                    _pendingObject = null;
                    var valueType = value.GetType();
                    if (valueType == typeof(PlantModel))
                    {
                        CloneAndBindingPlant((PlantModel)value);

                        if (_cloneSelectedPlant.PlantId > 0)
                            _addAreaIcon.IsEnabled = true;
                    }
                    else if (valueType == typeof(AreaModel))
                    {
                        _areaMenuIcon.IsEnabled = true;
                        _statusMenuIcon.IsEnabled = true;
                        ContentPaneHeader = _areaHeader;
                        CloneAndBindingArea((AreaModel)value);

                        if (_cloneSelectedArea.PlantId > 0)
                            _addCellIcon.IsEnabled = true;
                    }
                    else if (valueType == typeof(CellModel))
                    {
                        _areaMenuIcon.IsEnabled = true;
                        _statusMenuIcon.IsEnabled = true;
                        ContentPaneHeader = _cellHeader;
                        CloneAndBindingCell((CellModel)value);
                    }
                }

                _selectedObject = value;
                OnPropertyChanged("SelectedObject");
            }
        }

        public PlantModel CloneSelectedPlant
        {
            get { return _cloneSelectedPlant; }
            set
            {
                if (_cloneSelectedPlant == value) return;
                _cloneSelectedPlant = value;
                OnPropertyChanged("CloneSelectedPlant");
            }
        }

        public AreaModel CloneSelectedArea
        {
            get { return _cloneSelectedArea; }
            set
            {
                if (_cloneSelectedArea == value) return;
                _cloneSelectedArea = value;
                OnPropertyChanged("CloneSelectedArea");
            }
        }

        public CellModel CloneSelectedCell
        {
            get { return _cloneSelectedCell; }
            set
            {
                if (_cloneSelectedCell == value) return;
                _cloneSelectedCell = value;
                OnPropertyChanged("CloneSelectedCell");
            }
        }

        public string ContentPaneHeader
        {
            get { return _contentPaneHeader; }
            set
            {
                if (_contentPaneHeader == value) return;
                _contentPaneHeader = value;
                OnPropertyChanged("ContentPaneHeader");
            }
        }

        #endregion

        #region Methods

        #region Plants
        private void OnAddPlant()
        {
            SelectedObject = new PlantModel { IsAddNew = true, Enabled = true, DateFormat = _defaultDateFormat };
        }

        private void DoSavePlant(object obj)
        {
            ErrorMessage = null;
            if (!CloneSelectedPlant.IsValid())
            {
                IsClosing = false;
                _pendingObject = null;
                return;
            }

            var item = new PlantItem
            {
                PlantId = CloneSelectedPlant.PlantId,
                PlantName = CloneSelectedPlant.PlantName.TrimSafety(),
                Description = CloneSelectedPlant.Description.TrimSafety(),
                DateFormat = string.IsNullOrEmpty(CloneSelectedPlant.DateFormat.TrimSafety()) ? _defaultDateFormat : CloneSelectedPlant.DateFormat.TrimSafety(),
                Enabled = CloneSelectedPlant.Enabled,
            };

            ErrorMessage = null;
            IsBusy = true;
            if (CloneSelectedPlant.IsAddNew)
                DoAsync(PlantProvider.InsertPlant, InsertPlantCompleted, item);
            else
                DoAsync(PlantProvider.UpdatePlant, UpdatePlantCompleted, item);
        }

        private void DoDeletePlant(object obj)
        {
            ErrorMessage = null;
            if (MessageBox.Show(string.Format(FormatString.DeleteItemFormat, "plant"), TitleString.ConfirmDeleteTitle, MessageBoxButton.YesNo) == MessageBoxResult.No)
                return;

            IsBusy = true;
            DoAsync(PlantProvider.DeletePlant, DeletePlantCompleted, CloneSelectedPlant.PlantId);
        }

        private void DoCancelPlant(object obj)
        {
            ErrorMessage = null;
            CloneAndBindingPlant((PlantModel)_selectedObject);
        }

        private void UpdatePlantCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as SaveDataResponse<PlantItem>;
            IsBusy = false;

            if (response == null || !response.Success)
            {
                if (response != null)
                    CloneSelectedPlant.ErrorMessage = response.Error.Description;

                CloneSelectedPlant.IsCancelEnable = false;
                _pendingObject = null;
                IsClosing = false;
                return;
            }

            if (IsClosing)
            {
                IsBusy = true;
                DoAsync(SecurityProvider.Logout, LogoutCompleted);
                return;
            }

            var selectedPlant = (PlantModel)_selectedObject;

            selectedPlant.PlantName = response.Data.PlantName;
            selectedPlant.Description = response.Data.Description;
            selectedPlant.Enabled = response.Data.Enabled;
            selectedPlant.DateFormat = response.Data.DateFormat;
            selectedPlant.LastUpdatedDate = response.Data.LastUpdatedDate.ToString(FormatString.DateTimeFormat);
            selectedPlant.LastUpdatedBy = response.Data.LastUpdatedBy;

            selectedPlant.IsChange = false;
            selectedPlant.ErrorMessage = null;
            selectedPlant.IsCancelEnable = false;

            CloneAndBindingPlant(selectedPlant);

            SetPendingObject();
        }

        private void InsertPlantCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as SaveDataResponse<PlantItem>;
            IsBusy = false;

            if (response == null || !response.Success)
            {
                if (response != null)
                    CloneSelectedPlant.ErrorMessage = response.Error.Description;

                CloneSelectedPlant.IsCancelEnable = false;
                _pendingObject = null;
                IsClosing = false;
                return;
            }

            if (IsClosing)
            {
                IsBusy = true;
                DoAsync(SecurityProvider.Logout, LogoutCompleted);
                return;
            }

            var newPlant = new PlantModel();
            newPlant.PlantId = response.Data.PlantId;
            newPlant.PlantName = response.Data.PlantName;
            newPlant.Description = response.Data.Description;
            newPlant.DateFormat = response.Data.DateFormat;
            newPlant.Enabled = response.Data.Enabled;
            newPlant.LastUpdatedDate = response.Data.LastUpdatedDate.ToString(FormatString.DateTimeFormat);
            newPlant.LastUpdatedBy = response.Data.LastUpdatedBy;
            newPlant.CreatedDate = response.Data.CreatedDate.ToString(FormatString.DateTimeFormat);
            newPlant.CreatedBy = response.Data.CreatedBy;

            Plants.Add(newPlant);

            _selectedObject = null;
            SelectedObject = newPlant;

            SetPendingObject();
        }

        private void DeletePlantCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as DeleteDataResponse;
            IsBusy = false;

            if (response == null || !response.Success)
            {
                CloneSelectedPlant.ErrorMessage = response.Error.Description;
                _pendingObject = null;
                IsClosing = false;
                return;
            }

            if (IsClosing)
            {
                NavigateBack();
                return;
            }

            CloneSelectedPlant = null;
            SelectedObject = null;

            var item = Plants.FirstOrDefault(t => t.PlantId == response.DataId);
            if (item != null)
                Plants.Remove(item);
        }

        private void CloneAndBindingPlant(PlantModel plantModel)
        {
            CloneSelectedPlant = SmartReflection.CloneModel(plantModel);
            CloneSelectedPlant.ShouldValidate = true;
        }
        #endregion

        #region Areas
        private void OnAddArea()
        {
            var plant = SelectedObject as PlantModel;
            if (plant == null || plant.PlantId <= 0)
                return;

            SelectedObject = new AreaModel { IsAddNew = true, Enabled = true, PlantId = plant.PlantId };
        }

        private void DoSaveArea(object obj)
        {
            ErrorMessage = null;
            if (!CloneSelectedArea.IsValid())
            {
                IsClosing = false;
                _pendingObject = null;
                return;
            }

            var item = new AreaItem
            {
                AreaId = CloneSelectedArea.AreaId,
                PlantId = CloneSelectedArea.PlantId,
                AreaName = CloneSelectedArea.AreaName.TrimSafety(),
                Description = CloneSelectedArea.Description.TrimSafety(),
                Enabled = CloneSelectedArea.Enabled,
            };

            ErrorMessage = null;
            IsBusy = true;
            if (CloneSelectedArea.IsAddNew)
                DoAsync(AreaProvider.InsertArea, InsertAreaCompleted, item);
            else
                DoAsync(AreaProvider.UpdateArea, UpdateAreaCompleted, item);
        }

        private void DoDeleteArea(object obj)
        {
            ErrorMessage = null;
            if (MessageBox.Show(string.Format(FormatString.DeleteItemFormat, "area"), TitleString.ConfirmDeleteTitle, MessageBoxButton.YesNo) == MessageBoxResult.No)
                return;

            IsBusy = true;
            DoAsync(AreaProvider.DeleteArea, DeleteAreaCompleted, CloneSelectedArea.AreaId);
        }

        private void DoCancelArea(object obj)
        {
            ErrorMessage = null;
            CloneAndBindingArea((AreaModel)_selectedObject);
        }

        private void UpdateAreaCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as SaveDataResponse<AreaItem>;
            IsBusy = false;

            if (response == null || !response.Success)
            {
                if (response != null)
                    CloneSelectedArea.ErrorMessage = response.Error.Description;

                CloneSelectedArea.IsCancelEnable = false;
                _pendingObject = null;
                IsClosing = false;
                return;
            }

            if (IsClosing)
            {
                IsBusy = true;
                DoAsync(SecurityProvider.Logout, LogoutCompleted);
                return;
            }

            var selectedArea = (AreaModel)_selectedObject;

            selectedArea.AreaName = response.Data.AreaName;
            selectedArea.Description = response.Data.Description;
            selectedArea.Enabled = response.Data.Enabled;
            selectedArea.LastUpdatedDate = response.Data.LastUpdatedDate.ToString(FormatString.DateTimeFormat);
            selectedArea.LastUpdatedBy = response.Data.LastUpdatedBy;

            selectedArea.IsChange = false;
            selectedArea.ErrorMessage = null;
            selectedArea.IsCancelEnable = false;

            CloneAndBindingArea(selectedArea);

            SetPendingObject();
        }

        private void InsertAreaCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as SaveDataResponse<AreaItem>;
            IsBusy = false;

            if (response == null || !response.Success)
            {
                if (response != null)
                    CloneSelectedArea.ErrorMessage = response.Error.Description;

                CloneSelectedArea.IsCancelEnable = false;
                _pendingObject = null;
                IsClosing = false;
                return;
            }

            if (IsClosing)
            {
                IsBusy = true;
                DoAsync(SecurityProvider.Logout, LogoutCompleted);
                return;
            }

            var newArea = new AreaModel();
            newArea.AreaId = response.Data.AreaId;
            newArea.PlantId = response.Data.PlantId;
            newArea.AreaName = response.Data.AreaName;
            newArea.Description = response.Data.Description;
            newArea.Enabled = response.Data.Enabled;
            newArea.LastUpdatedDate = response.Data.LastUpdatedDate.ToString(FormatString.DateTimeFormat);
            newArea.LastUpdatedBy = response.Data.LastUpdatedBy;
            newArea.CreatedDate = response.Data.CreatedDate.ToString(FormatString.DateTimeFormat);
            newArea.CreatedBy = response.Data.CreatedBy;

            var plant = Plants.FirstOrDefault(t => t.PlantId == newArea.PlantId);
            if (plant != null)
                plant.Areas.Add(newArea);

            _selectedObject = null;
            SelectedObject = newArea;

            SetPendingObject();
        }

        private void DeleteAreaCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as DeleteDataResponse;
            IsBusy = false;

            if (response == null || !response.Success)
            {
                CloneSelectedArea.ErrorMessage = response.Error.Description;
                _pendingObject = null;
                IsClosing = false;
                return;
            }

            if (IsClosing)
            {
                NavigateBack();
                return;
            }

            CloneSelectedArea = null;
            SelectedObject = null;

            var plant = Plants.FirstOrDefault(t => t.Areas != null && t.Areas.Any(a => a.AreaId == response.DataId));
            if (plant != null)
            {
                var item = plant.Areas.FirstOrDefault(t => t.AreaId == response.DataId);
                if (item != null)
                    plant.Areas.Remove(item);
            }
        }

        private void CloneAndBindingArea(AreaModel areaModel)
        {
            CloneSelectedArea = SmartReflection.CloneModel(areaModel);
            CloneSelectedArea.ShouldValidate = true;
        }
        #endregion

        #region Cells
        private void OnAddCell()
        {
            var area = SelectedObject as AreaModel;
            if (area == null || area.AreaId <= 0)
                return;

            SelectedObject = new CellModel { IsAddNew = true, Enabled = true, AreaId = area.AreaId };
        }

        private void DoSaveCell(object obj)
        {
            ErrorMessage = null;
            if (!CloneSelectedCell.IsValid())
            {
                IsClosing = false;
                _pendingObject = null;
                return;
            }

            var item = new CellItem
            {
                CellId = CloneSelectedCell.CellId,
                AreaId = CloneSelectedCell.AreaId,
                CellName = CloneSelectedCell.CellName.TrimSafety(),
                Description = CloneSelectedCell.Description.TrimSafety(),
                Password = CloneSelectedCell.Password.TrimSafety(),
                Enabled = CloneSelectedCell.Enabled,
                VisiCentralGroup = (byte)CloneSelectedCell.VisiCentralGroup,
                VisiCentralRow = CloneSelectedCell.VisiCentralRow,
                VisiCentralColumn = CloneSelectedCell.VisiCentralColumn
            };

            ErrorMessage = null;
            IsBusy = true;
            if (CloneSelectedCell.IsAddNew)
                DoAsync(CellProvider.InsertCell, InsertCellCompleted, item);
            else
                DoAsync(CellProvider.UpdateCell, UpdateCellCompleted, item);
        }

        private void DoDeleteCell(object obj)
        {
            ErrorMessage = null;
            if (MessageBox.Show(string.Format(FormatString.DeleteItemFormat, "cell"), TitleString.ConfirmDeleteTitle, MessageBoxButton.YesNo) == MessageBoxResult.No)
                return;

            IsBusy = true;
            DoAsync(CellProvider.DeleteCell, DeleteCellCompleted, CloneSelectedCell.CellId);
        }

        private void DoCancelCell(object obj)
        {
            ErrorMessage = null;
            CloneAndBindingCell((CellModel)_selectedObject);
        }

        private void UpdateCellCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as SaveDataResponse<CellItem>;
            IsBusy = false;

            if (response == null || !response.Success)
            {
                if (response != null)
                    CloneSelectedCell.ErrorMessage = response.Error.Description;

                CloneSelectedCell.IsCancelEnable = false;
                _pendingObject = null;
                IsClosing = false;
                return;
            }

            if (IsClosing)
            {
                IsBusy = true;
                DoAsync(SecurityProvider.Logout, LogoutCompleted);
                return;
            }

            var selectedCell = (CellModel)_selectedObject;

            selectedCell.CellName = response.Data.CellName;
            selectedCell.Description = response.Data.Description;
            selectedCell.Password = response.Data.Password;
            selectedCell.Enabled = response.Data.Enabled;
            selectedCell.VisiCentralGroup = (CellModel.VisiCentralGroupEnum)response.Data.VisiCentralGroup;
            selectedCell.VisiCentralRow = response.Data.VisiCentralRow;
            selectedCell.VisiCentralColumn = response.Data.VisiCentralColumn;
            selectedCell.LastUpdatedDate = response.Data.LastUpdatedDate.ToString(FormatString.DateTimeFormat);
            selectedCell.LastUpdatedBy = response.Data.LastUpdatedBy;

            selectedCell.IsChange = false;
            selectedCell.ErrorMessage = null;
            selectedCell.IsCancelEnable = false;

            CloneAndBindingCell(selectedCell);

            SetPendingObject();
        }

        private void InsertCellCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as SaveDataResponse<CellItem>;
            IsBusy = false;

            if (response == null || !response.Success)
            {
                if (response != null)
                    CloneSelectedCell.ErrorMessage = response.Error.Description;

                CloneSelectedCell.IsCancelEnable = false;
                _pendingObject = null;
                IsClosing = false;
                return;
            }

            if (IsClosing)
            {
                IsBusy = true;
                DoAsync(SecurityProvider.Logout, LogoutCompleted);
                return;
            }

            var newCell = new CellModel();
            newCell.CellId = response.Data.CellId;
            newCell.AreaId = response.Data.AreaId;
            newCell.CellName = response.Data.CellName;
            newCell.Description = response.Data.Description;
            newCell.Password = response.Data.Password;
            newCell.Enabled = response.Data.Enabled;
            newCell.VisiCentralGroup = (CellModel.VisiCentralGroupEnum)response.Data.VisiCentralGroup;
            newCell.VisiCentralRow = response.Data.VisiCentralRow;
            newCell.VisiCentralColumn = response.Data.VisiCentralColumn;
            newCell.LastUpdatedDate = response.Data.LastUpdatedDate.ToString(FormatString.DateTimeFormat);
            newCell.LastUpdatedBy = response.Data.LastUpdatedBy;
            newCell.LastUpdatedDate = response.Data.LastUpdatedDate.ToString(FormatString.DateTimeFormat);
            newCell.LastUpdatedBy = response.Data.LastUpdatedBy;
            newCell.CreatedDate = response.Data.CreatedDate.ToString(FormatString.DateTimeFormat);
            newCell.CreatedBy = response.Data.CreatedBy;

            var plant = Plants.FirstOrDefault(t => t.Areas != null && t.Areas.Any(a => a.AreaId == newCell.AreaId));
            if (plant != null)
            {
                var area = plant.Areas.FirstOrDefault(t => t.AreaId == newCell.AreaId);
                if (area != null)
                    area.Cells.Add(newCell);
            }
            _selectedObject = null;
            SelectedObject = newCell;

            SetPendingObject();
        }

        private void DeleteCellCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as DeleteDataResponse;
            IsBusy = false;

            if (response == null || !response.Success)
            {
                CloneSelectedCell.ErrorMessage = response.Error.Description;
                _pendingObject = null;
                IsClosing = false;
                return;
            }

            if (IsClosing)
            {
                NavigateBack();
                return;
            }

            CloneSelectedCell = null;
            SelectedObject = null;

            var plant = Plants.FirstOrDefault(t => t.Areas != null && t.Areas.Any(a => a.Cells != null && a.Cells.Any(c => c.CellId == response.DataId)));
            if (plant != null)
            {
                var area = plant.Areas.FirstOrDefault(t => t.Cells != null && t.Cells.Any(a => a.CellId == response.DataId));
                if (area != null)
                {
                    var item = area.Cells.FirstOrDefault(t => t.CellId == response.DataId);
                    if (item != null)
                        area.Cells.Remove(item);
                }
            }
        }

        private void CloneAndBindingCell(CellModel cellModel)
        {
            CloneSelectedCell = SmartReflection.CloneModel(cellModel);
            CloneSelectedCell.ShouldValidate = true;
        }
        #endregion

        #region Callback methods

        private void OnLogout()
        {
            IsClosing = true;
            if (CloneSelectedPlant != null && IsPlantPendingChange(null))
                return;
            if (CloneSelectedArea != null && IsAreaPendingChange(null))
                return;
            if (CloneSelectedCell != null && IsCellPendingChange(null))
                return;

            IsBusy = true;
            DoAsync(SecurityProvider.Logout, LogoutCompleted);
        }

        private void UserMenuClick()
        {
            NavigationManager.NavigateTo(new UserView(), null);
        }

        private void ProductsMenuClick()
        {
            NavigationManager.NavigateTo(new ProductView(), null);
        }

        private void EditAreaMenuClick()
        {
            if (SelectedObject == null)
                return;

            Type type = SelectedObject.GetType();
            if (type == typeof(AreaModel) || type == typeof(CellModel))
            {
                var areaId = type == typeof(AreaModel) ? ((AreaModel)SelectedObject).AreaId : ((CellModel)SelectedObject).AreaId;
                var currentArea = _backupAreas.FirstOrDefault(t => t.AreaId == areaId);
                NavigationManager.NavigateTo(new AreaDetailsView(), currentArea);
            }
        }

        private void VisiBoardStatusMenuClick()
        {
            if (SelectedObject == null)
                return;

            Type type = SelectedObject.GetType();
            if (type == typeof(AreaModel) || type == typeof(CellModel))
            {
                var areaId = type == typeof(AreaModel) ? ((AreaModel)SelectedObject).AreaId : ((CellModel)SelectedObject).AreaId;
                var currentArea = _backupAreas.FirstOrDefault(t => t.AreaId == areaId);
                NavigationManager.NavigateTo(new StatusView(), currentArea);
            }
        }

        private void GetPlantsCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as GetDataResponse<IList<PlantItem>>;
            IsBusy = false;

            if (response == null || !response.Success)
            {
                if (response != null)
                    ErrorMessage = response.Error.Description;
                return;
            }

            PopulateDataToList(response.Data);
        }

        private void LogoutCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as SignOutResponse;
            IsBusy = false;

            if (response == null || !response.Success)
            {
                if (response != null)
                    ErrorMessage = response.Error.Description;
                return;
            }

            NavigationManager.LoggedInUser = null;
            FileHelper.DeleteAllFilesInFolder();
            NavigationManager.NavigateTo(new LoginView(), null);

        }

        #endregion

        #region Helpers

        private void NavigateBack()
        {
            IsBusy = true;
            DoAsync(SecurityProvider.Logout, LogoutCompleted);
        }

        private void SetPendingObject()
        {
            if (_pendingObject != null)
            {
                SelectedObject = _pendingObject;
                _pendingObject = null;
            }
        }

        private bool IsPlantPendingChange(object value)
        {
            if (_cloneSelectedPlant != null && _cloneSelectedPlant.HasChange())
            {
                switch (ConfirmDialog.Show())
                {
                    case SaveChangesDialogResult.Discard:
                        return false;
                    case SaveChangesDialogResult.Save:
                        _pendingObject = value;
                        DoSavePlant(null);
                        return true;
                    case SaveChangesDialogResult.Resume:
                        IsClosing = false;
                        _pendingObject = null;
                        return true;
                }
            }
            return false;
        }

        private bool IsAreaPendingChange(object value)
        {
            if (_cloneSelectedArea != null && _cloneSelectedArea.HasChange())
            {
                switch (ConfirmDialog.Show())
                {
                    case SaveChangesDialogResult.Discard:
                        return false;
                    case SaveChangesDialogResult.Save:
                        _pendingObject = value;
                        DoSaveArea(null);
                        return true;
                    case SaveChangesDialogResult.Resume:
                        IsClosing = false;
                        _pendingObject = null;
                        return true;
                }
            }
            return false;
        }

        private bool IsCellPendingChange(object value)
        {
            if (_cloneSelectedCell != null && _cloneSelectedCell.HasChange())
            {
                switch (ConfirmDialog.Show())
                {
                    case SaveChangesDialogResult.Discard:
                        return false;
                    case SaveChangesDialogResult.Save:
                        _pendingObject = value;
                        DoSaveCell(null);
                        return true;
                    case SaveChangesDialogResult.Resume:
                        IsClosing = false;
                        _pendingObject = null;
                        return true;
                }
            }
            return false;
        }

        private void PopulateDataToList(IList<PlantItem> list)
        {
            Plants = new ObservableCollection<PlantModel>();
            _backupPlants = new List<PlantModel>();
            _backupAreas = new List<AreaModel>();
            _backupCells = new List<CellModel>();
            if (list != null)
                foreach (var plantItem in list)
                {
                    var plantModel = new PlantModel
                    {
                        PlantId = plantItem.PlantId,
                        PlantName = plantItem.PlantName,
                        Description = plantItem.Description,
                        Enabled = plantItem.Enabled,
                        DateFormat = plantItem.DateFormat,
                        CreatedBy = plantItem.CreatedBy,
                        LastUpdatedBy = plantItem.LastUpdatedBy,
                        CreatedDate = plantItem.CreatedDate.ToString(FormatString.DateTimeFormat),
                        LastUpdatedDate = plantItem.LastUpdatedDate.ToString(FormatString.DateTimeFormat),
                        Areas = new ObservableCollection<AreaModel>(),
                    };

                    if (plantItem.Areas != null)
                        foreach (var areaItem in plantItem.Areas)
                        {
                            var areaModel = new AreaModel
                            {
                                AreaId = areaItem.AreaId,
                                PlantId = areaItem.PlantId,
                                AreaName = areaItem.AreaName,
                                Description = areaItem.Description,
                                Enabled = areaItem.Enabled,
                                CreatedBy = areaItem.CreatedBy,
                                LastUpdatedBy = areaItem.LastUpdatedBy,
                                CreatedDate = areaItem.CreatedDate.ToString(FormatString.DateTimeFormat),
                                LastUpdatedDate = areaItem.LastUpdatedDate.ToString(FormatString.DateTimeFormat),
                                Cells = new ObservableCollection<CellModel>(),
                            };
                            if (areaItem.Cells != null)
                                foreach (var cellItem in areaItem.Cells)
                                {
                                    var cellModel = new CellModel
                                    {
                                        CellId = cellItem.CellId,
                                        AreaId = cellItem.AreaId,
                                        CellName = cellItem.CellName,
                                        Description = cellItem.Description,
                                        Enabled = cellItem.Enabled,
                                        VisiCentralGroup = (CellModel.VisiCentralGroupEnum)cellItem.VisiCentralGroup,
                                        VisiCentralColumn = cellItem.VisiCentralColumn,
                                        VisiCentralRow = cellItem.VisiCentralRow,
                                        CreatedBy = cellItem.CreatedBy,
                                        LastUpdatedBy = cellItem.LastUpdatedBy,
                                        CreatedDate = cellItem.CreatedDate.ToString(FormatString.DateTimeFormat),
                                        LastUpdatedDate = cellItem.LastUpdatedDate.ToString(FormatString.DateTimeFormat),
                                    };
                                    areaModel.Cells.Add(cellModel);
                                    _backupCells.Add((CellModel)SmartReflection.CloneObject(cellModel));
                                }
                            plantModel.Areas.Add(areaModel);
                            _backupAreas.Add((AreaModel)SmartReflection.CloneObject(areaModel));
                        }
                    Plants.Add(plantModel);
                    _backupPlants.Add((PlantModel)SmartReflection.CloneObject(plantModel));
                }
        }
        #endregion

        #endregion

        #region Navigation Framwork
        public override void OnNavigate(object obj)
        {
            ErrorMessage = null;
            ContentPaneHeader = _plantHeader;
            IsBusy = true;
            DoAsync(PlantProvider.GetPlants, GetPlantsCompleted);
        }

        public override void OnLeave()
        {
        }
        #endregion

    }
}
